package taskRunner

import (
	"VideoServer/scheduler/dbops"
	"errors"
	"log"
	"os"
	"sync"
)

func deleteVideo(vid string) error {
	err := os.Remove(VIDEO_PATH + vid)
	//TODO 这里需要加上video文件的后缀吗？,这里不写那么在客户端就必须加上后缀?
	if err != nil && !os.IsNotExist(err) {
		//如果文件不存在，认为已经删除过，不是错误
		log.Printf("deleting video error:%v", err)
		return err
	}
	return nil
}

func VideoClearDispatcher(dc dataChan) error {
	res, err := dbops.ReadVideoDeletionRecord(3) //每次读cnt条
	if err != nil {
		log.Printf("video clear dispatcher error:%v", err)
		return err
	}
	if len(res) == 0 {
		return errors.New("all tasks finished")
	}
	for _, id := range res {
		dc <- id //将读出的id写到dataChan里面
	}
	return nil
}

func VideoClearExecutor(dc dataChan) error {
	//TODO:这里存在重复读写问题，后续考虑改进
	//存在多个协程，所以存在多个错误，因此要使用map存放
	errMap := &sync.Map{}

forLoop:
	for {
		select {
		case vid := <-dc:
			go func(id interface{}) {
				if err := deleteVideo(id.(string)); err != nil {
					errMap.Store(id, err)
					return
				}
				if err := dbops.DelVideoDeletionRecord(id.(string)); err != nil {
					errMap.Store(id, err)
					return
				}
			}(vid) //TODO 理解这里为什么要写成参数vid传入，不直接在闭包内部使用外部变量？
		default:
			break forLoop
		}
	}
	var err error
	//遍历errMap，如果存在err就停止迭代，return这个err
	errMap.Range(
		func(key, value interface{}) bool {
			err = value.(error)
			if err != nil {
				return false
			} else {
				return true
			}
		})
	return err
}
